package com.szakul.pdf.viewer.dao.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;

import com.szakul.pdf.viewer.dao.beans.Leaf;
import com.szakul.pdf.viewer.dao.beans.Node;
import com.szakul.pdf.viewer.dao.beans.TreeDao;


/**
 * 
 * @author Lukasz
 *
 */
public class TreeDaoImpl implements TreeDao {

	private static final Logger LOGGER = Logger.getLogger(TreeDaoImpl.class);
	
	private final SessionFactory sessionFactory;
	
	
	/**
	 * Constructor.
	 * 
	 * @param sessionFactory
	 */
	public TreeDaoImpl(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	@Transactional
	public int createLeaf(Leaf leaf) {
		
		if(leaf == null) {
			throw new IllegalArgumentException("Leaf cannot be null.");
		}
		
        Integer id = -1;

        final Session session = sessionFactory.getCurrentSession();

        id = (Integer)session.save(leaf);

        return id;
	}

	@Transactional
	public int createNode(Node node) {

		if(node == null) {
			throw new IllegalArgumentException("Node cannot be null.");
		}
		
        Integer id = -1;

        final Session session = sessionFactory.getCurrentSession();

        id = (Integer)session.save(node);

        return id;	
	}

	@Transactional
	public void updateLeaf(Leaf leaf) {
		

        final Session session = sessionFactory.getCurrentSession();

        session.update(leaf);

	}

	@Transactional
	public void updateNode(Node node) {
		
        final Session session = sessionFactory.getCurrentSession();

        session.update(node);
	}

	public List<Node> getAllNodes() {
		
		final Session session = sessionFactory.getCurrentSession();
		
		 ArrayList<Node> result = (ArrayList<Node>) session.createQuery("from Node").list();

		 if(result == null) {
			 result = (ArrayList<Node>) Collections.EMPTY_LIST;
		 } 
		 
		 return result;
	}

	public Leaf getLeafById(int id) {
		
		final Session session = sessionFactory.getCurrentSession();
		return (Leaf) session.createQuery("from Leaf where id = ?").setInteger(0, id).uniqueResult();

	}

	public int getNodesCount() {
		
		final Session session = sessionFactory.getCurrentSession();
		int count = ((Long)session.createQuery("select count(*) from Node").uniqueResult()).intValue();
		return count;
	}

	public List<Leaf> getNodeLeafs(Node node) {
		
		final Session session = sessionFactory.getCurrentSession();
		return session.createQuery("from Leaf where nodeId = ?").setInteger(0, node.getId()).list();
	}

	public void deleteLeaf(Leaf leaf) {
		
		final Session session = sessionFactory.getCurrentSession();
		
		LOGGER.debug("Leaf: " + leaf.getName() + " belongs to node: " + leaf.getNode().getName());
	
		Node node = leaf.getNode();
		
		node.getLeaf().remove(leaf);
		
		session.update(node);
		
		LOGGER.debug("Leaf removed from node. Node size: " + node.getLeaf().size());
		
		session.delete(leaf);

	}

	public void deleteNode(Node node) {
		
		LOGGER.debug("Deleting node: " + node.getId());
		final Session session = sessionFactory.getCurrentSession();
		session.update(node);
		node.getLeaf().clear();
		session.update(node);
		LOGGER.debug("Node has " + node.getLeaf().size() + " leafs");
		
		int deleted = session.createQuery("delete from Leaf where nodeId = ?").setInteger(0, node.getId()).executeUpdate();
		LOGGER.debug(deleted + " leafs was deleted");
		session.delete(node);
	}

}
